/*!
 * \file test_cpu_helper.cpp
 * \brief CpuHelper工具类的单元测试
 * 
 * \details 测试CpuHelper类的所有功能，包括：
 *          - CPU核心数量查询
 *          - 线程CPU绑定功能
 *          - 跨平台兼容性测试
 *          - 边界条件和异常处理
 */

#include <gtest/gtest.h>
#include <thread>
#include <vector>
#include <chrono>
#include "CpuHelper.hpp"

/*!
 * \brief CpuHelper测试夹具类
 * 
 * \details 为CpuHelper测试提供统一的测试环境
 */
class CpuHelperTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 获取系统CPU核心数
        cpu_cores = CpuHelper::get_cpu_cores();
    }

    void TearDown() override {
        // 清理资源（如果需要）
    }

    uint32_t cpu_cores;
};

/*!
 * \brief 测试CPU核心数量查询功能
 * 
 * \details 验证get_cpu_cores函数能否正确返回系统CPU核心数
 */
TEST_F(CpuHelperTest, TestGetCpuCores) {
    // 测试基本功能
    uint32_t cores = CpuHelper::get_cpu_cores();
    
    // CPU核心数应该大于0
    EXPECT_GT(cores, 0U);
    
    // 在现代系统中，CPU核心数通常不会超过256
    EXPECT_LE(cores, 256U);
    
    // 测试多次调用的一致性（静态缓存）
    uint32_t cores2 = CpuHelper::get_cpu_cores();
    EXPECT_EQ(cores, cores2);
    
    // 验证与标准库的一致性
    uint32_t std_cores = std::thread::hardware_concurrency();
    EXPECT_EQ(cores, std_cores);
}

/*!
 * \brief 测试CPU核心数量的合理性
 * 
 * \details 验证返回的CPU核心数在合理范围内
 */
TEST_F(CpuHelperTest, TestCpuCoresReasonability) {
    uint32_t cores = CpuHelper::get_cpu_cores();
    
    // 现代系统至少应该有1个核心
    EXPECT_GE(cores, 1U);
    
    // 对于大多数个人电脑和服务器，核心数通常在1-128之间
    EXPECT_LE(cores, 128U);
    
    // 验证是否为2的幂（许多系统的核心数是2的幂）
    // 注意：这不是强制要求，只是常见情况
    bool is_power_of_two = (cores & (cores - 1)) == 0;
    if (cores <= 64) {
        // 对于较小的核心数，更可能是2的幂
        // 但这不是必须的，所以只是记录而不断言
        std::cout << "CPU cores: " << cores 
                  << (is_power_of_two ? " (power of 2)" : " (not power of 2)") << std::endl;
    }
}

/*!
 * \brief 测试线程CPU绑定功能的基本操作
 * 
 * \details 验证bind_core函数的基本功能和返回值
 */
TEST_F(CpuHelperTest, TestBindCoreBasic) {
    if (cpu_cores == 0) {
        GTEST_SKIP() << "无法获取CPU核心数，跳过绑定测试";
    }
    
    // 测试绑定到第一个核心
    bool result = CpuHelper::bind_core(0);
    
#ifdef __APPLE__
    // macOS总是返回true（但实际不绑定）
    EXPECT_TRUE(result);
#else
    // 其他平台应该能够成功绑定（如果有权限）
    // 注意：在某些受限环境中可能失败，这是正常的
    if (!result) {
        std::cout << "警告：无法绑定到CPU核心0，可能是权限不足" << std::endl;
    }
#endif
}

/*!
 * \brief 测试绑定到所有可用CPU核心
 * 
 * \details 验证能否成功绑定到系统中的每个CPU核心
 */
TEST_F(CpuHelperTest, TestBindAllCores) {
    if (cpu_cores == 0) {
        GTEST_SKIP() << "无法获取CPU核心数，跳过绑定测试";
    }
    
    std::vector<bool> bind_results;
    
    // 尝试绑定到每个核心
    for (uint32_t i = 0; i < cpu_cores; ++i) {
        bool result = CpuHelper::bind_core(i);
        bind_results.push_back(result);
        
#ifdef __APPLE__
        // macOS总是返回true
        EXPECT_TRUE(result) << "macOS应该总是返回true，核心: " << i;
#endif
    }
    
    // 统计成功绑定的核心数
    int successful_binds = 0;
    for (bool result : bind_results) {
        if (result) successful_binds++;
    }
    
    std::cout << "成功绑定到 " << successful_binds << "/" << cpu_cores << " 个CPU核心" << std::endl;
    
#ifdef __APPLE__
    // macOS应该全部成功（虽然实际不绑定）
    EXPECT_EQ(successful_binds, static_cast<int>(cpu_cores));
#endif
}

/*!
 * \brief 测试边界条件和无效输入
 * 
 * \details 验证bind_core函数对无效输入的处理
 */
TEST_F(CpuHelperTest, TestBindCoreBoundaryConditions) {
    if (cpu_cores == 0) {
        GTEST_SKIP() << "无法获取CPU核心数，跳过边界测试";
    }
    
    // 测试绑定到不存在的核心（超出范围）
    bool result_invalid = CpuHelper::bind_core(cpu_cores);  // 应该失败
    
#ifdef __APPLE__
    // macOS总是返回true
    EXPECT_TRUE(result_invalid);
#else
    // 其他平台应该返回false
    EXPECT_FALSE(result_invalid) << "绑定到不存在的核心应该失败";
#endif
    
    // 测试绑定到远超范围的核心
    bool result_far_invalid = CpuHelper::bind_core(9999);
    
#ifdef __APPLE__
    // macOS总是返回true
    EXPECT_TRUE(result_far_invalid);
#else
    // 其他平台应该返回false
    EXPECT_FALSE(result_far_invalid) << "绑定到远超范围的核心应该失败";
#endif
    
    // 测试最大有效核心索引
    if (cpu_cores > 0) {
        bool result_max_valid = CpuHelper::bind_core(cpu_cores - 1);
        
#ifdef __APPLE__
        EXPECT_TRUE(result_max_valid);
#else
        // 最大有效索引应该能够绑定（如果有权限）
        if (!result_max_valid) {
            std::cout << "警告：无法绑定到最大有效核心 " << (cpu_cores - 1) << std::endl;
        }
#endif
    }
}

/*!
 * \brief 测试多线程环境下的CPU绑定
 * 
 * \details 验证多个线程同时进行CPU绑定的行为
 */
TEST_F(CpuHelperTest, TestMultiThreadBinding) {
    if (cpu_cores < 2) {
        GTEST_SKIP() << "需要至少2个CPU核心进行多线程测试";
    }
    
    const int num_threads = std::min(static_cast<int>(cpu_cores), 4);
    std::vector<std::thread> threads;
    std::vector<bool> results(num_threads);
    
    // 创建多个线程，每个绑定到不同的核心
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([i, &results]() {
            // 每个线程绑定到对应的核心
            results[i] = CpuHelper::bind_core(static_cast<uint32_t>(i));
            
            // 执行一些计算来验证绑定效果
            volatile int sum = 0;
            for (int j = 0; j < 1000; ++j) {
                sum += j;
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证结果
    int successful_binds = 0;
    for (int i = 0; i < num_threads; ++i) {
#ifdef __APPLE__
        EXPECT_TRUE(results[i]) << "macOS线程 " << i << " 绑定应该成功";
#endif
        if (results[i]) {
            successful_binds++;
        }
    }
    
    std::cout << "多线程测试：" << successful_binds << "/" << num_threads << " 个线程成功绑定" << std::endl;
}

/*!
 * \brief 测试CPU绑定的性能影响
 * 
 * \details 简单测试CPU绑定对性能的影响（主要是验证功能正常）
 */
TEST_F(CpuHelperTest, TestBindingPerformance) {
    if (cpu_cores == 0) {
        GTEST_SKIP() << "无法获取CPU核心数，跳过性能测试";
    }
    
    const int iterations = 10000;
    
    // 测试不绑定CPU的执行时间
    auto start_unbound = std::chrono::high_resolution_clock::now();
    volatile int sum_unbound = 0;
    for (int i = 0; i < iterations; ++i) {
        sum_unbound += i * i;
    }
    auto end_unbound = std::chrono::high_resolution_clock::now();
    auto duration_unbound = std::chrono::duration_cast<std::chrono::microseconds>(
        end_unbound - start_unbound);
    
    // 绑定到第一个核心后测试执行时间
    bool bind_result = CpuHelper::bind_core(0);
    
    auto start_bound = std::chrono::high_resolution_clock::now();
    volatile int sum_bound = 0;
    for (int i = 0; i < iterations; ++i) {
        sum_bound += i * i;
    }
    auto end_bound = std::chrono::high_resolution_clock::now();
    auto duration_bound = std::chrono::duration_cast<std::chrono::microseconds>(
        end_bound - start_bound);
    
    // 验证计算结果一致
    EXPECT_EQ(sum_unbound, sum_bound);
    
    std::cout << "性能测试结果:" << std::endl;
    std::cout << "  未绑定CPU: " << duration_unbound.count() << " 微秒" << std::endl;
    std::cout << "  绑定CPU: " << duration_bound.count() << " 微秒" << std::endl;
    std::cout << "  绑定结果: " << (bind_result ? "成功" : "失败") << std::endl;
    
    // 性能测试不做严格断言，因为结果可能因系统负载而变化
    // 只要程序能正常执行就算通过
    EXPECT_TRUE(true);
}

/*!
 * \brief 测试重复绑定同一核心
 * 
 * \details 验证重复绑定同一CPU核心的行为
 */
TEST_F(CpuHelperTest, TestRepeatedBinding) {
    if (cpu_cores == 0) {
        GTEST_SKIP() << "无法获取CPU核心数，跳过重复绑定测试";
    }
    
    // 多次绑定到同一个核心
    for (int i = 0; i < 5; ++i) {
        bool result = CpuHelper::bind_core(0);
        
#ifdef __APPLE__
        EXPECT_TRUE(result) << "macOS第 " << (i+1) << " 次绑定应该成功";
#else
        // 其他平台的重复绑定行为可能因系统而异
        if (!result) {
            std::cout << "警告：第 " << (i+1) << " 次绑定失败" << std::endl;
        }
#endif
    }
}

/*!
 * \brief 测试跨平台兼容性
 * 
 * \details 验证不同平台下的行为一致性
 */
TEST_F(CpuHelperTest, TestCrossPlatformCompatibility) {
    // 测试函数调用不会崩溃
    EXPECT_NO_THROW({
        uint32_t cores = CpuHelper::get_cpu_cores();
        bool result = CpuHelper::bind_core(0);
    });
    
    // 验证平台特定行为
#ifdef _WIN32
    std::cout << "运行在Windows平台" << std::endl;
#elif defined(__linux__)
    std::cout << "运行在Linux平台" << std::endl;
#elif defined(__APPLE__)
    std::cout << "运行在macOS平台" << std::endl;
    // macOS的bind_core总是返回true但不实际绑定
    EXPECT_TRUE(CpuHelper::bind_core(0));
    EXPECT_TRUE(CpuHelper::bind_core(9999));  // 即使无效索引也返回true
#else
    std::cout << "运行在其他Unix平台" << std::endl;
#endif
}

/*!
 * \brief 测试静态方法的线程安全性
 * 
 * \details 验证静态方法在多线程环境下的安全性
 */
TEST_F(CpuHelperTest, TestThreadSafety) {
    const int num_threads = 10;
    std::vector<std::thread> threads;
    std::vector<uint32_t> core_counts(num_threads);
    
    // 多个线程同时调用get_cpu_cores
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([i, &core_counts]() {
            core_counts[i] = CpuHelper::get_cpu_cores();
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证所有线程得到相同的结果
    for (int i = 1; i < num_threads; ++i) {
        EXPECT_EQ(core_counts[0], core_counts[i]) 
            << "线程 " << i << " 得到不同的CPU核心数";
    }
}

/*!
 * \brief 测试极端情况处理
 * 
 * \details 验证极端输入情况的处理
 */
TEST_F(CpuHelperTest, TestExtremeConditions) {
    // 测试最大可能的核心索引
    bool result_max = CpuHelper::bind_core(UINT32_MAX);
    
#ifdef __APPLE__
    EXPECT_TRUE(result_max);
#else
    EXPECT_FALSE(result_max) << "绑定到UINT32_MAX应该失败";
#endif
    
    // 测试接近最大值的索引
    bool result_near_max = CpuHelper::bind_core(UINT32_MAX - 1);
    
#ifdef __APPLE__
    EXPECT_TRUE(result_near_max);
#else
    EXPECT_FALSE(result_near_max) << "绑定到接近最大值的索引应该失败";
#endif
} 